package com.jvtd.nettyim.im.protocol;

import com.jvtd.nettyim.im.protocol.command.Command;
import com.jvtd.nettyim.im.protocol.request.LoginRequestPacket;
import com.jvtd.nettyim.im.protocol.request.MessageRequestPacket;
import com.jvtd.nettyim.im.protocol.response.LoginResponsePacket;
import com.jvtd.nettyim.im.protocol.response.MessageResponsePacket;
import com.jvtd.nettyim.im.serialize.Serializer;
import com.jvtd.nettyim.im.serialize.impl.JSONSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Created by neal.zhang
 * @date 2020/5/27 - 20:18
 */
public class PacketCode {

    public static final int MAGIC_NUMBER = 0x123456;
    public static final PacketCode INSTANCE = new PacketCode();
    private static final Map<Byte,Class<? extends Packet>> packetMap;
    private static final Map<Byte, Serializer> serializerMap;

    static {
        packetMap = new HashMap<>();
        packetMap.put(Command.LOGIN_REQUEST, LoginRequestPacket.class);
        packetMap.put(Command.LOGIN_RESPONSE, LoginResponsePacket.class);
        packetMap.put(Command.MESSAGE_REQUEST, MessageRequestPacket.class);
        packetMap.put(Command.MESSAGE_RESPONSE, MessageResponsePacket.class);
        serializerMap=new HashMap<>();
        Serializer serializer = new JSONSerializer();
        serializerMap.put(serializer.getSerializerAlgorithm(),serializer);
    }

    /**
     * 序列化
     * @param packet
     * @param buf
     */
    public void encode(Packet packet, ByteBuf buf) {
        byte[] bytes = Serializer.DEFAULT.serialize(packet);
        buf.writeInt(MAGIC_NUMBER);
        buf.writeByte(packet.getVersion());
        buf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        buf.writeByte(packet.getCommand());
        buf.writeInt(bytes.length);
        buf.writeBytes(bytes);
    }

    /**
     * 反序列化
     * @param buf
     * @return
     */
    public Packet decode(ByteBuf buf){
        //跳过魔数
        buf.skipBytes(4);
        //跳过版本号
        buf.skipBytes(1);
        //读取序列化标识算法
        byte serializeAlgorithm = buf.readByte();
        byte command = buf.readByte();
        int dataLength = buf.readInt();
        byte[] bytes = new byte[dataLength];
        //将数据读入bytes中
        buf.readBytes(bytes);
        //获取类型
        Class<? extends Packet> requestType = getRequestType(command);
        Serializer serializer = getSerializer(serializeAlgorithm);

        if (requestType != null && serializer != null) {
            return serializer.deserialize(requestType, bytes);
        }
        return null;
    }

    private Serializer getSerializer(byte serializeAlgorithm) {
        return serializerMap.get(serializeAlgorithm);
    }

    private Class<? extends Packet> getRequestType(byte command) {
        return packetMap.get(command);
    }


}
